package com.sea.operate.service.impl;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.ObjectMetadata;
import com.codecrane.core.Constants;
import com.codecrane.core.power.entity.PowerUser;
import com.codecrane.core.web.Ajax;
import com.codecrane.core.web.AjaxReturn;
import com.codecrane.core.web.BatchImportUtils;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.sea.operate.entity.Related;
import com.sea.operate.entity.RelatedSku;
import com.sea.operate.mapper.RelatedSkuMapper;
import com.sea.operate.service.RelatedService;
import com.sea.operate.service.RelatedSkuService;
import com.sea.product.entity.Channel;
import com.sea.product.entity.Product;
import com.sea.product.service.ChannelService;
import com.sea.product.service.ProductService;
import org.apache.commons.lang.StringUtils;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.text.NumberFormat;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;


/**
 * @author 陈鸿飞
 */
@Service
public class RelatedSkuServiceImpl implements RelatedSkuService {

    @Autowired
    private RelatedSkuMapper relatedSkuMapper;
    @Autowired
    private ProductService productService;
    @Autowired
    private RelatedService relatedService;
    @Autowired
    private ChannelService channelService;

    public static void main(String[] args) {
        String fileUrl = "http://cozylux.oss-cn-beijing.aliyuncs.com/c38239f9-a14e-480a-bdd6-75f943a961bf.pdf?Expires=...";

        try {
            List<String> codes = readBarcodesFromPdfUrl(fileUrl);
            if (codes.isEmpty()) {
                System.out.println("未找到条形码");
            } else {
                for (String txt : codes) {
                    System.out.println("识别到条码内容: " + txt);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static List<String> readBarcodesFromPdfUrl(String fileUrl) throws Exception {
        URLConnection conn = new URL(fileUrl).openConnection();
        conn.setRequestProperty("User-Agent", "Mozilla/5.0");
        try (InputStream is = conn.getInputStream();
             PDDocument doc = PDDocument.load(is)) {

            PDFRenderer renderer = new PDFRenderer(doc);
            List<String> results = new ArrayList<>();

            Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
            hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
            hints.put(DecodeHintType.POSSIBLE_FORMATS, Arrays.asList(
                    BarcodeFormat.CODE_128,
                    BarcodeFormat.EAN_13,
                    BarcodeFormat.CODE_39,
                    BarcodeFormat.PDF_417,
                    BarcodeFormat.QR_CODE,
                    BarcodeFormat.DATA_MATRIX
            ));

            for (int i = 0; i < doc.getNumberOfPages(); i++) {
                BufferedImage img = renderer.renderImageWithDPI(i, 300, ImageType.GRAY);
                BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(
                        new BufferedImageLuminanceSource(img)));
                try {
                    Result result = new MultiFormatReader().decode(bitmap, hints);
                    results.add("页 " + (i+1) + ": [" + result.getBarcodeFormat() + "] " + result.getText());
                } catch (NotFoundException e) {
                    // 本页未找到条码
                }
            }
            return results;
        }
    }



    @Override
    public List<RelatedSku> findByCnd(RelatedSku relatedSku) {
        return relatedSkuMapper.findByCnd(relatedSku);
    }

    @Override
    public int save(RelatedSku relatedSku) {
        return relatedSkuMapper.insert(relatedSku);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importRelated(InputStream inputStream, String fileName) throws Exception {
        Workbook workBook = BatchImportUtils.getWorkBook(inputStream, fileName);
        List<Sheet> sheets = BatchImportUtils.getSheets(workBook);
        if (null != sheets && sheets.size() > 0) {
            Sheet sheet = sheets.get(0);
            List<RelatedSku> list = BatchImportUtils.iteratorForSku(sheet);
            if (null == list || list.size() == 0) {
                throw new Exception("请至少保存一条SKU信息！");
            } else {
                PowerUser user = (PowerUser) SecurityUtils.getSubject().getSession().getAttribute(Constants.CURRENT_USER_SESSION);
                for(RelatedSku relatedSku:list){
                    RelatedSku sku = findByChannelSku(relatedSku.getRelatedChannelName(), relatedSku.getRelatedSku());
                    Product product = productService.findBySku(relatedSku.getRelatedSku());
                    if(null==product){
                        throw new RuntimeException("【"+relatedSku.getRelatedSku()+"】不存在！");
                    }
                    Channel channel = channelService.findByChannelName(relatedSku.getRelatedChannelName());
                    if(null==channel){
                        throw new RuntimeException("【"+relatedSku.getRelatedChannelName()+"】不存在！");
                    }
                    if(StringUtils.isBlank(relatedSku.getRelatedOperateName())){
                        relatedSku.setRelatedOperateName(user.getUserRealname());
                    }
                    if(null!=sku){
                        relatedSku.setRelatedProductName(product.getProductName());
                        relatedSku.setId(sku.getId());
                         usave(relatedSku);
                    }else {
                        relatedSku.setRelatedProductName(product.getProductName());
                        save(relatedSku);
                    }
                }

                updateListingName();
            }
        }
    }

    @Override
    public RelatedSku findByChannelSku(String relatedChannelName, String relatedSku) {
        return relatedSkuMapper.findByChannelSku(relatedChannelName,relatedSku);
    }

    @Override
    public RelatedSku findById(Integer id) {
        return relatedSkuMapper.findById(id);
    }

    @Override
    public int usave(RelatedSku relatedSku) {
        return relatedSkuMapper.update(relatedSku);
    }

    @Override
    public RelatedSku findByChannelSku(RelatedSku s) {
        RelatedSku relatedSku = relatedSkuMapper.findByChannelSku(s.getRelatedChannelName(), s.getRelatedSku());
        Related related = relatedService.findByAsin(relatedSku.getRelatedAsin(),relatedSku.getRelatedChannelName());
        relatedSku.setRelatedListingName(related.getRelatedListing());
        return relatedSku;
    }

    @Override
    public RelatedSku findByUnique(RelatedSku relatedSku) {
        return relatedSkuMapper.findByUnique(relatedSku);
    }

    @Override
    public Integer updateListingName() {
        return relatedSkuMapper.updateListingName();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importRelatedFlag(MultipartFile file, String fileName) throws Exception {
        File zipFile = null;
        String errMsg="";
        if (file.equals("") || file.getSize() <= 0) {
            file = null;
        } else {
            InputStream ins = null;
            try {
                ins = file.getInputStream();
                zipFile = new File(file.getOriginalFilename());
                inputStreamToFile(ins, zipFile);
                ZipFile zip = new ZipFile(zipFile, Charset.forName("GBK"));
                int ypxhrs = 0;
                for (Enumeration enumeration = zip.entries(); enumeration.hasMoreElements(); ) {
                    ZipEntry entry = (ZipEntry) enumeration.nextElement();
                    ypxhrs++;
                    // 创建一个数值格式化对象
                    NumberFormat numberFormat = NumberFormat.getInstance();
                    // 设置精确到小数点后2位
                    numberFormat.setMaximumFractionDigits(2);
                    if (entry.isDirectory()) {
                        continue;
                    }
                    //文件的
                    String filename1 = entry.getName();
                    System.out.println(filename1);
                    int lastIndex = filename1.lastIndexOf(".");
                    System.out.println(lastIndex);
                    String xh = filename1.substring(0, lastIndex);
                    //获取SKU
                    System.out.println(xh);

                    RelatedSku relatedSku=new RelatedSku();
                    relatedSku.setRelatedSku(xh);
                    InputStream inputStream = zip.getInputStream(entry);
                    InputStream newInputStream = zip.getInputStream(entry);
                    String fnSku = decodeBarCode(inputStream, xh);
                    relatedSku.setRelatedFnSku(fnSku);
                    List<RelatedSku> byCnd = findByCnd(relatedSku);
                    if(byCnd.size()==0){
                        errMsg+=xh+",";
                    }
                    if(StringUtils.isBlank(errMsg)) {
                        //将zipEntry转成输入流
                        String s = uploadFile(newInputStream, filename1);
                        if(StringUtils.isBlank(s)){
                            throw new RuntimeException("该SKU文件上传异常:"+xh);
                        }else{
                            relatedSku.setRelatedFile(s);
                            updateRelatedFile(relatedSku);
                        }
                    }
                    inputStream.close();
                }
                if(StringUtils.isNotBlank(errMsg)) {
                    throw new RuntimeException("尚未查询到该SKU:"+errMsg);
                }
            } catch (IOException e) {
                e.printStackTrace();

            } finally {
                if (ins != null) {
                    ins.close();
                }
            }
        }
    }

    public String uploadFile(InputStream inputStream, String fileName) {
        AjaxReturn result = Ajax.fail().setMsg("上传失败！");
        try {

            System.out.println(inputStream.available());
            OSSClient ossClient=new OSSClient("http://oss-cn-beijing.aliyuncs.com",
                    "LTAI4G55LJEk8nARtrjYngou",
                    "XPbdMs0xrRGAsmKVm9VYC8bSTTuFhl");


            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType("application/octet-stream");


            ossClient.putObject("cozylux-related", fileName, inputStream,metadata);
            // 关闭OSSClient。
            ossClient.shutdown();
            Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 50);
            String url = ossClient.generatePresignedUrl("cozylux-related", fileName, expiration).toString();
            return url;
        }catch (Exception e){
            return "";
        }
    }

    public static void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.flush();
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Integer updateRelatedFile(RelatedSku relatedSku) {
        return relatedSkuMapper.updateRelatedFile(relatedSku);
    }

    @Override
    public List<RelatedSku> findByProduceId(Integer produceId) {
        return relatedSkuMapper.findByProduceId(produceId);
    }

    @Override
    public List<RelatedSku> findRelatedFileByProduceId(Integer produceId) {
        return relatedSkuMapper.findRelatedFileByProduceId(produceId);
    }

    @Override
    public String decodeBarCode(InputStream inputStream, String sku) throws Exception {

        try (PDDocument document = PDDocument.load(inputStream)) {
            PDFRenderer renderer = new PDFRenderer(document);
            BufferedImage image = renderer.renderImageWithDPI(0, 300, ImageType.GRAY); // 只处理第 1 页

            LuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

            Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
            hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
            hints.put(DecodeHintType.POSSIBLE_FORMATS, Arrays.asList(
                    BarcodeFormat.CODE_128,
                    BarcodeFormat.CODE_39,
                    BarcodeFormat.EAN_13,
                    BarcodeFormat.PDF_417,
                    BarcodeFormat.QR_CODE,
                    BarcodeFormat.DATA_MATRIX
            ));

            Result result = new MultiFormatReader().decode(bitmap, hints);
            System.out.println("解析的条形码为："+result.getText());
            return result.getText();

        } catch (NotFoundException e) {
            System.out.println("未识别到条形码");
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


}
